package net.biancheng.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import net.biancheng.bean.SysDept;
import net.biancheng.common.constant.CommonConstant;
import net.biancheng.common.core.bean.TreeSelect;
import net.biancheng.common.core.text.Convert;
import net.biancheng.common.enums.SysDataStatus;
import net.biancheng.exception.ServiceException;
import net.biancheng.common.utils.DateUtils;
import net.biancheng.common.utils.SecurityUtils;
import net.biancheng.mapper.SysDeptMapper;
import net.biancheng.mapper.SysUserMapper;
import net.biancheng.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 部门Service业务层处理
 * 
 * @author lb
 * @date 2024-01-25
 */
@Service
public class SysDeptServiceImpl implements ISysDeptService
{
    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询部门
     * 
     * @param id 部门主键
     * @return 部门
     */
    @Override
    public SysDept selectSysDeptById(Long id)
    {
        return sysDeptMapper.selectSysDeptById(id);
    }

    /**
     * 查询部门列表
     * 
     * @param sysDept 部门
     * @return 部门
     */
    @Override
    public List<SysDept> selectSysDeptList(SysDept sysDept)
    {
        return sysDeptMapper.selectSysDeptList(sysDept);
    }

    /**
     * 构建前端所需树结构菜单
     * @param depts
     * @return
     */
    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts){
        List<SysDept> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        //将所有部门ID存入临时集合，用于后面判断是否是顶级节点
        for (SysDept dept: depts){
            tempList.add(dept.getId());
        }
        //遍历处理菜单子节点
        for (Iterator<SysDept> iterator = depts.iterator(); iterator.hasNext();){
            SysDept dept = iterator.next();
            //判断当前菜单父节点是否是顶级节点
            //不存在则是顶级节点，遍历该父节点的所有子节点
            if(!tempList.contains(dept.getParentId())){
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()){
            returnList = depts;
        }
        return returnList;
    }

    /**
     * 构建前端所需下拉树选择部门结构
     * @param depts
     * @return
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts){
        List<SysDept> treeList = buildDeptTree(depts);
        return treeList.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 新增部门
     * 
     * @param sysDept 部门
     * @return 结果
     */
    @Override
    public int insertSysDept(SysDept sysDept)
    {
        SysDept parentDept = sysDeptMapper.selectSysDeptById(sysDept.getParentId());
        if (parentDept != null){
            //如果父节点不为正常状态,则不允许新增子节点
            if (!SysDataStatus.OK.getCode().equals(parentDept.getStatus())){
                throw new ServiceException("部门停用，不允许新增");
            }
            //设置祖级列表
            sysDept.setAncestors(parentDept.getAncestors() + "," + sysDept.getParentId());
        } else {
            //设置祖级列表为父级ID
            sysDept.setAncestors(sysDept.getParentId().toString());
        }
        sysDept.setCreateBy(SecurityUtils.getUsername());
        sysDept.setCreateTime(DateUtils.getNowDate());
        return sysDeptMapper.insertSysDept(sysDept);
    }

    /**
     * 修改部门
     * 
     * @param sysDept 部门
     * @return 结果
     */
    @Override
    public int updateSysDept(SysDept sysDept)
    {
        SysDept parentDept = sysDeptMapper.selectSysDeptById(sysDept.getParentId());
        SysDept oldDept = sysDeptMapper.selectSysDeptById(sysDept.getId());
        if (oldDept != null && parentDept != null) {
            String newAncestors = parentDept.getAncestors() + "," + sysDept.getParentId();
            String oldAncestors = oldDept.getAncestors();
            //判断是否修改过父级
            if (!oldDept.getParentId().equals(sysDept.getParentId())) {
                //如果修改过，判断当前部门下是否存在子部门，存在需修改所有子部门的祖级ID
                if (sysDeptMapper.hasChildByParentId(sysDept.getId()) > 0) {
                    updateSysDeptChildren(sysDept.getId(), newAncestors, oldAncestors);
                }
            }
            //重新设置祖级列表
            sysDept.setAncestors(newAncestors);
        }
        //如果该部门由停用改为启用状态，并且非顶级部门
        if (oldDept != null && SysDataStatus.DISABLE.getCode().equals(oldDept.getStatus()) && SysDataStatus.OK.getCode().equals(sysDept.getStatus()) && !CommonConstant.PARENT_ID.equals(sysDept.getParentId())) {
            //则启用该部门的所有上级部门
            updateParentDeptStatusNormal(sysDept);
        }

        sysDept.setUpdateBy(SecurityUtils.getUsername());
        sysDept.setUpdateTime(DateUtils.getNowDate());
        return sysDeptMapper.updateSysDept(sysDept);
    }

    /**
     * 修改子部门祖级信息
     *
     * @param deptId 被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateSysDeptChildren(Long deptId, String newAncestors, String oldAncestors)
    {
        List<SysDept> children = sysDeptMapper.selectChildrenDeptByParentId(deptId);
        for (SysDept child : children)
        {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0)
        {
            //批量更新子部门列表
            sysDeptMapper.updateSysDeptChildren(children);
        }
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentDeptStatusNormal(SysDept dept)
    {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        sysDeptMapper.updateDeptStatusNormal(deptIds);
    }

    /**
     * 批量删除部门
     * 
     * @param ids 需要删除的部门主键
     * @return 结果
     */
    @Override
    public int deleteSysDeptByIds(Long[] ids)
    {
        return sysDeptMapper.deleteSysDeptByIds(ids);
    }

    /**
     * 删除部门信息
     * 
     * @param id 部门主键
     * @return 结果
     */
    @Override
    public int deleteSysDeptById(Long id)
    {
        //判断当前部门是否存在子级，存在不允许删除
        if (sysDeptMapper.hasChildByParentId(id) > 0)
        {
            throw new ServiceException("存在下级部门,不允许删除");
        }
        //判断当前部门是否已分配给用户，已分配不允许删除
        if (sysUserMapper.checkDeptExistUser(id) > 0)
        {
            throw new ServiceException("部门存在用户,不允许删除");
        }
        return sysDeptMapper.deleteSysDeptById(id);
    }

    /**
     * 递归列表
     *
     * @param list
     * @param d
     */
    private void recursionFn(List<SysDept> list, SysDept d)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, d);
        d.setChildren(childList);
        for (SysDept dChild : childList)
        {
            if (hasChild(list, dChild))
            {
                recursionFn(list, dChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept d)
    {
        List<SysDept> dlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext())
        {
            SysDept n = (SysDept) it.next();
            if (n.getParentId().longValue() == d.getId().longValue())
            {
                dlist.add(n);
            }
        }
        return dlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list, SysDept d)
    {
        return getChildList(list, d).size() > 0;
    }

}
